/*
 * @(#)Mersenne.java	1.0 Apr 26, 2008
 *
 *	The MIT License
 *
 *	Copyright (c) 2008 Malachi de AElfweald <malachid@gmail.com>
 *
 *	Permission is hereby granted, free of charge, to any person obtaining a copy
 *	of this software and associated documentation files (the "Software"), to deal
 *	in the Software without restriction, including without limitation the rights
 *	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *	copies of the Software, and to permit persons to whom the Software is
 *	furnished to do so, subject to the following conditions:
 *
 *	The above copyright notice and this permission notice shall be included in
 *	all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *	THE SOFTWARE.
 */
package org.eoti.math.prime;

import java.math.BigInteger;
import java.util.*;

public class Mersenne
{
	protected static BigInteger two = BigInteger.valueOf(2);
	protected static String[] primes = new String[]{
			"2","3","5","7","13","17","19","31","61","89","107","127","521","607",		// M1-M14
			"1279","2203","2281","3217","4253","4423","9689","9941","11213", "19937",	// M15-M23
			"21701","23209","44497","86243","110503","132049","216091","756839",		// M24-M32
			"859433","1257787","1398269","2976221","3021377","6972593","13466917",		// M33-M39
			// indexes of rest could be wrong
			"20996011","24036583","25964951","30402457","32582657"						// M40?-M44?
	};

	protected BigInteger value;
	protected int index;
	public Mersenne(int index)
	{
		this.index = index;
		value = two.pow(Integer.parseInt(primes[index-1]));
		value = value.subtract(BigInteger.ONE);
	}

	// Per common Mersenne Prime tables, index is 1-based
	public int getIndex(){return index;}

	public Integer getN(){return Integer.parseInt(primes[index-1]);}
	public Integer getBitLength(){return getN();}

	public Integer getDigitLength(){return (""+getValue()).length();}

	public BigInteger getValue(){return value;}

	public static Iterable<Mersenne> iterator()
	{
		return new Iterable<Mersenne>()
		{
			public Iterator<Mersenne> iterator()
			{
				return new MersenneIter();
			}
		};
	}

	static class MersenneIter
		implements Iterator<Mersenne>
	{
		protected int currIndex = 0;

		MersenneIter(){}

		public boolean hasNext()
		{
			return currIndex <= primes.length;
		}

		public Mersenne next()
		{
			return new Mersenne(++currIndex);
		}

		public void remove()
		{
			throw new UnsupportedOperationException("Remove not implemented");
		}
	}
}
